#ifndef COREDBAPI_H
#define COREDBAPI_H

#include "FarmDataBases.h"

//hax
#define exit(x) { outputAllDatabases(); exitScreen(); printGreen("Shutting down.\nInput to continue.\n"); inputToContinue(); exit(x); }
#define BUFFER_SIZE 256

void getUpToDateVersionsDB(){
	FILE* upToDateVersionsDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *serviceID, *serviceVer;

	upToDateVersionsDB_iFile = fopen("UpToDateVersionsDB.txt", "r");
	assertMem(upToDateVersionsDB_iFile );

	while( fgets(lineBuffer, BUFFER_SIZE, upToDateVersionsDB_iFile) ){
		serviceID = strtok(lineBuffer, ",\n");
		serviceVer = strtok(NULL, ",\n");
		upToDateVersionsDBPush(atoi(serviceID), atoi(serviceVer));
	}

	fclose(upToDateVersionsDB_iFile);
}
void getInstalledServicesDB(){
	FILE* installedServicesDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *serviceName, *serviceID, *serviceVer, *serverID;

	installedServicesDB_iFile = fopen("InstalledServicesDB.txt", "r");
	assertMem(installedServicesDB_iFile );
	
	while( fgets(lineBuffer, BUFFER_SIZE, installedServicesDB_iFile) ){
		serviceName = strtok(lineBuffer, ",\n");
		serviceID = strtok(NULL, ",\n");
		serviceVer = strtok(NULL, ",\n");
		serverID = strtok(NULL, ",\n");
		installedServicesDBPush(serviceName, atoi(serviceID), atoi(serviceVer), atoi(serverID));
	}

	fclose(installedServicesDB_iFile);
}
void getUpdateServersDB(){
	FILE* updateServersDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *addr, *ID;
	
	updateServersDB_iFile = fopen("UpdateServersDB.txt", "r");
	assertMem(updateServersDB_iFile );
	
	while( fgets(lineBuffer, BUFFER_SIZE, updateServersDB_iFile) ){
		addr = strtok(lineBuffer, ",\n");
		ID = strtok(NULL, ",\n");
		updateServersDBPush(addr, atoi(ID));
	}

	fclose(updateServersDB_iFile);
}
void getSupportedServicesDB(){
	FILE* supportedServicesDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *service, *ID;

	supportedServicesDB_iFile = fopen("SupportedServicesDB.txt", "r");
	assertMem(supportedServicesDB_iFile );

	while( fgets(lineBuffer, BUFFER_SIZE, supportedServicesDB_iFile) ){
		service = strtok(lineBuffer, ",\n");
		ID = strtok(NULL, ",\n");
		supportedServicesDBPush(service, atoi(ID));
	}

	fclose(supportedServicesDB_iFile);
}
void getSuperUsersDB(){
	FILE* superUserDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *userName, *userPass;

	superUserDB_iFile = fopen("SuperUsersDB.txt", "r");
	assertMem(superUserDB_iFile );

	while( fgets(lineBuffer, BUFFER_SIZE, superUserDB_iFile) ){
		userName = strtok(lineBuffer, ",\n");
		userPass = strtok(NULL, ",\n");
		superUsersDBPush(userName, userPass);
	}

	fclose(superUserDB_iFile);
}
void getMessagesDB(){
	FILE* messagesDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *message, *ID;

	messagesDB_iFile = fopen("MessagesDB.txt", "r");
	assertMem(messagesDB_iFile );

	while( fgets(lineBuffer, BUFFER_SIZE, messagesDB_iFile) ){
		message = strtok(lineBuffer, ",");
		ID = strtok(NULL, ",\n");
		messagesDBPush(message, atoi(ID));
	}

	fclose(messagesDB_iFile);

}
void getPrivateUsersDB(){
	FILE* privateUsersDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *userName, *userPass, *IDchar, *userType;
	int ID[SERVERID_LENGTH] ={0}, i=0;

	privateUsersDB_iFile = fopen("PrivateUsersDB.txt", "r");
	assertMem( privateUsersDB_iFile );

	while( fgets(lineBuffer, BUFFER_SIZE, privateUsersDB_iFile) ){
		userName = strtok(lineBuffer, ",\n");
		userPass = strtok(NULL, ",\n");
		userType = strtok(NULL, ",\n");
		while( IDchar = strtok(NULL, ",\n"))
		{
			if(i < SERVERID_LENGTH-1 )
				ID[i++] = atoi(IDchar);
		}
		i=0;
		privateUsersDBPush(userName, userPass, ID, atoi(userType));
		while(i < SERVERID_LENGTH)
			ID[i++] = 0;
		i=0;
	}

	fclose(privateUsersDB_iFile);


}
void getServersDB(){

	FILE* serversDB_iFile; 
	char lineBuffer[BUFFER_SIZE];
	char *addr, *ID;

	serversDB_iFile = fopen("ServersDB.txt", "r");
	assertMem( serversDB_iFile );

	while( fgets(lineBuffer, BUFFER_SIZE, serversDB_iFile) ){
		addr = strtok(lineBuffer, ",\n");
		ID = strtok(NULL, ",\n");
		serversDBPush(addr, atoi(ID));
	}

	fclose(serversDB_iFile);
}
void getAllDataBases(){
	getServersDB();
	getPrivateUsersDB();
	getMessagesDB();
	getSuperUsersDB();
	getSupportedServicesDB();
	getUpdateServersDB();
	getInstalledServicesDB();
	getUpToDateVersionsDB();
}

int getServerID(char *serverAddr){
	ServerNode *curr = (servers_DB)?servers_DB->head : NULL;

	while(curr)
	{
		if( !strcmp(curr->address, serverAddr) )
			return curr->ID;
		curr = curr->next;
	}

	return 0;
}
char* getServerAddr(int serverID){
	ServerNode *curr = (servers_DB)?servers_DB->head : NULL;

	while(curr)
	{
		if( curr->ID == serverID )
			return curr->address;
		curr = curr->next;
	}

	return NULL;
}
char* getUserPass(char *userName){
	PrivateUserNode *currPrivate = (privateUsers_DB)?privateUsers_DB->head : NULL;
	SuperUsersNode* currSuper = (superUsers_DB)?superUsers_DB->head : NULL;

	while(currPrivate)
	{
		if( !strcmp(currPrivate->userName, userName) )
			return currPrivate->userPass;
		currPrivate = currPrivate->next;
	}

	while(currSuper)
	{
		if( !strcmp(currSuper->userName, userName) )
			return currSuper->userPass;
		currSuper = currSuper->next;
	}

	return NULL;
}
int getUserType(char *userName){
	PrivateUserNode *currPrivate = (privateUsers_DB)?privateUsers_DB->head : NULL;
	SuperUsersNode* currSuper = (superUsers_DB)?superUsers_DB->head : NULL;

	while(currPrivate)
	{
		if( !strcmp(currPrivate->userName, userName) )
			return currPrivate->userType;
		currPrivate = currPrivate->next;
	}

	while(currSuper)
	{
		if( !strcmp(currSuper->userName, userName) )
			return currSuper->userType;
		currSuper = currSuper->next;
	}

	return 0;
}
int* getUserServerID(char *userName){
	PrivateUserNode *currPrivate = (privateUsers_DB)?privateUsers_DB->head : NULL;

	while(currPrivate)
	{
		if( !strcmp(currPrivate->userName, userName) )
			return currPrivate->serverID;
		currPrivate = currPrivate->next;
	}
	return NULL;
}
int getServiceID(char *serviceName){
	SupportedServicesNode *currService = supportedServicesDBGetHead();

	while( currService )
	{
		if( !strcmp( serviceName, supportedServicesNodeGetServiceName(currService)))
			return supportedServicesNodeGetServiceID(currService);
		currService = supportedServicesNodeGetNext(currService);
	}

	return 0;
}
int getServiceUpToDateVer(int serviceID){
	UpToDateVersionsNode *currUpToDate = upToDateVersionsDBGetHead();
	int currServiceVer = 0;
	while( currUpToDate )
	{
		if( serviceID==upToDateVersionsNodeGetServiceID(currUpToDate) )
			currServiceVer = upToDateVersionsNodeGetServiceVersion(currUpToDate);
		currUpToDate = upToDateVersionsNodeGetNext(currUpToDate);
	}

	return currServiceVer;
}


void outputDB_UpToDateVersions(){
	UpToDateVersionsNode *currNode = NULL;

	FILE* upToDateVersionsDB_iFile; 

	upToDateVersionsDB_iFile = fopen("UpToDateVersionsDB.txt", "w");
	assertMem(upToDateVersionsDB_iFile );

	if( upToDateVersions_DB )
		currNode = upToDateVersions_DB->head;

	while( currNode ){
		
		fprintf(upToDateVersionsDB_iFile,"%d,%d",currNode->serviceID,currNode->serviceVerson);
		currNode = currNode->next;
		if (currNode)
			fprintf(upToDateVersionsDB_iFile,"\n");

	}
	fclose(upToDateVersionsDB_iFile);
}
void outputDB_InstalledServices(){
	InstalledServicesNode *currNode = NULL;
	FILE* installedServicesDB_iFile; 


	installedServicesDB_iFile = fopen("InstalledServicesDB.txt", "w");
	assertMem(installedServicesDB_iFile );
	
	if( installedServices_DB )
		currNode = installedServices_DB->head;

	while ( currNode ){

		fprintf(installedServicesDB_iFile,"%s,%d,%d,%d",currNode->serviceName,currNode->serviceID,currNode->serviceVersion,currNode->serverID);
		currNode = currNode->next;

		if ( currNode )
			fprintf(installedServicesDB_iFile,"\n");
	}
	fclose(installedServicesDB_iFile);
}
void outputDB_UpdateServers(){
	UpdateServerNode *currNode = NULL;

	FILE* updateServersDB_iFile; 
	updateServersDB_iFile = fopen("UpdateServersDB.txt", "w");
	assertMem(updateServersDB_iFile );
	

	if ( updateServers_DB )
		currNode = updateServers_DB->head;

	while ( currNode ){

		fprintf(updateServersDB_iFile,"%s,%d",currNode->address,currNode->serviceID);
		currNode = currNode->next;

		if( currNode)
			fprintf(updateServersDB_iFile,"\n");
	}
	fclose(updateServersDB_iFile);
}
void outputDB_SupportedServices(){
	SupportedServicesNode *currNode = NULL;

	FILE* supportedServicesDB_iFile;
	supportedServicesDB_iFile = fopen("SupportedServicesDB.txt", "w");
	assertMem(supportedServicesDB_iFile );
	

	if ( supportedServices_DB )
		currNode = supportedServices_DB->head;
	while ( currNode ){

		fprintf(supportedServicesDB_iFile,"%s,%d",currNode->serviceName, currNode->serviceID);
		currNode = currNode->next;

		if( currNode )
			fprintf(supportedServicesDB_iFile,"\n");
	}
	fclose(supportedServicesDB_iFile);
}
void outputDB_SuperUsers(){
	SuperUsersNode *currNode = NULL;
	FILE* superUserDB_iFile; 
	superUserDB_iFile = fopen("SuperUsersDB.txt", "w");
	assertMem(superUserDB_iFile );
	

	if ( superUsers_DB )
		currNode = superUsers_DB->head;

	while( currNode ){
		fprintf(superUserDB_iFile,"%s,%s",currNode->userName,currNode->userPass);
		currNode = currNode->next;

		if ( currNode )
			fprintf(superUserDB_iFile,"\n");

	}
	fclose(superUserDB_iFile);
}
void outputDB_Messages(){
	MessagesNode *currNode = NULL;
	FILE* messagesDB_iFile; 
	messagesDB_iFile = fopen("MessagesDB.txt", "w");
	assertMem(messagesDB_iFile );
	

	if ( messages_DB )
		currNode = messages_DB->head;

	while( currNode ){
		fprintf(messagesDB_iFile,"%s,%d",currNode->messages,currNode->ID);
		currNode = currNode->next;

		if( currNode )
			fprintf(messagesDB_iFile,"\n");
	}
	fclose(messagesDB_iFile);
}
void outputDB_PrivateUsers(){
	PrivateUserNode *currNode = NULL;
	int i = 0, currID = 0;
	FILE* privateUsersDB_iFile; 
	privateUsersDB_iFile = fopen("PrivateUsersDB.txt", "w");
	assertMem( privateUsersDB_iFile );
	

	if ( privateUsers_DB )
		currNode = privateUsers_DB->head;

	while( currNode ){
		fprintf(privateUsersDB_iFile,"%s,%s,%d,",currNode->userName,currNode->userPass,currNode->userType);
		while( currID = currNode->serverID[i]){
			fprintf(privateUsersDB_iFile,"%d",currID);
			i++;
			if ( currID = currNode->serverID[i] )
				fprintf(privateUsersDB_iFile,",");
		}
		i=0;
		
		currNode = currNode->next;
		if (currNode)
			fprintf(privateUsersDB_iFile,"\n");
	}
	fclose(privateUsersDB_iFile);
}
void outputDB_Servers(){
	ServerNode *currNode = NULL;
	FILE* serversDB_iFile; 
	serversDB_iFile = fopen("ServersDB.txt", "w");
	assertMem( serversDB_iFile );
	
	if ( servers_DB )
		currNode = servers_DB->head;

	while( currNode ){
		fprintf(serversDB_iFile,"%s,%d",currNode->address,currNode->ID);
		currNode = currNode->next;

		if ( currNode )
			fprintf(serversDB_iFile,"\n");
	}
	fclose(serversDB_iFile);
}
void outputAllDatabases(){
	outputDB_UpToDateVersions();
	outputDB_InstalledServices();
	outputDB_UpdateServers();
	outputDB_SupportedServices();
	outputDB_SuperUsers();
	outputDB_Messages();
	outputDB_PrivateUsers();
	outputDB_Servers();
}

#endif
